/**
 * Esta classe realiza o gerenciamento dos buscadores dos preditores
 */
package epibot.QualificaSites;

import epibot.BancoDeDados.ArmazenaDados.Fasta;
import epibot.BancoDeDados.Tabelas;
import epibot.EstruturasBiologicas.Epitopo;
import epibot.EstruturasBiologicas.Proteina;
import epibot.WebRobots.Bimas;
import epibot.WebRobots.IEDB_consensus;
import epibot.WebRobots.NETMHC;
import epibot.WebRobots.SYFPEITHI;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import javax.swing.SwingUtilities;

/**
 *
 * @author Rafael Tosta
 */
public class GerenciadorRobot_Calibragem extends Thread {

    private String tamanho;
    private String alelo;
    private ArrayList<String> motores;
    private ArrayList<Fasta> lista;
    private ArrayList<String[]> l_calibradores;
    private JPanelQualificaSites jp;
    private String nomeCalibragem;

    /**
     * Construtor
     *
     * @param jTextAreaAvisos
     */
    public GerenciadorRobot_Calibragem(JPanelQualificaSites jp, ArrayList<String> motores, ArrayList<Fasta> lista, ArrayList<String[]> l_calibradores,
            String tamanho, String alelo, String nomeCalibragem) {
        this.jp = jp;
        this.tamanho = tamanho;
        this.alelo = alelo;
        this.motores = motores;
        this.lista = lista;
        this.nomeCalibragem = nomeCalibragem;
        this.l_calibradores = l_calibradores;

    }

    public void print(final String t) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                jp.setjTextAreaQuery(t);
            }
        });
    }

    public void print_m(final String t) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                jp.setjTextAreaQuery_margem(t);
            }
        });
    }

    public void printNota(final String t) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                jp.setjTextNotes(t);
            }
        });

    }

    public void iniciaPBar(final int max) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                jp.iniciaPBar(max);
            }
        });

    }

    public void setValuePBar(final int v) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                jp.setValuePBar(v);
            }
        });

    }

    /*
     * Roda os motores de busca em uma thead para poder deixar a interface
     * gráfica sem travar e para a barra de progresso
     *
     * Apatir da lista de motores de busca é definido em quais sites será
     * utilizado na consulta
     */
    @Override
    public void run() {

        buscaSites();

    }

    public void buscaSites() {

        double somaBimas = 0.0, somaIEDB_consensus = 0.0,
                somaNETMHC = 0.0, somaSYFPEITHI = 0.0;

        iniciaPBar(lista.size());
        for (int i = 0; i < lista.size(); i++) {
            Fasta proteina = lista.get(i);
            print("Protein: " + proteina.getCodProteina());

            for (int j = 0; j < motores.size(); j++) {
                print_m(motores.get(j));

                if (motores.get(j).equals("Bimas")) {
                    //obtem aproteina pelo webRobot
                    Proteina p = executaBimas(proteina);

                    //para cada proteina a ser consultada já verifica a pontuação dos epítopos
                    if (p != null) {
                        ArrayList<Epitopo> ep = buscaEpitopo(p);
                        if (!ep.isEmpty()) {
                            for (int k = 0; k < ep.size(); k++) {
                                somaBimas = somaBimas + 1.0 / ep.get(k).getRank();
                            }
                        }
                    }
                }
                if (motores.get(j).equals("NETMHC")) {
                    //obtem aproteina pelo webRobot
                    Proteina p = executaNETMHC(proteina);

                    //para cada proteina a ser consultada já verifica a pontuação dos epítopos
                    if (p != null) {
                        ArrayList<Epitopo> ep = buscaEpitopo(p);
                        if (!ep.isEmpty()) {
                            for (int k = 0; k < ep.size(); k++) {
                                somaNETMHC = somaNETMHC + 1.0 / ep.get(k).getRank();
                            }
                        }
                    }
                }
                if (motores.get(j).equals("IEDB_consensus")) {
                    //obtem aproteina pelo webRobot
                    Proteina p = executaIEDB_consensus(proteina);

                    //para cada proteina a ser consultada já verifica a pontuação dos epítopos
                    if (p != null) {
                        ArrayList<Epitopo> ep = buscaEpitopo(p);
                        if (!ep.isEmpty()) {
                            for (int k = 0; k < ep.size(); k++) {
                                somaIEDB_consensus = somaIEDB_consensus + 1.0 / ep.get(k).getRank();
                            }
                        }
                    }
                }
                if (motores.get(j).equals("SYFPEITHI")) {
                    //obtem aproteina pelo webRobot
                    Proteina p = executaSYFPEITHI(proteina);

                    //para cada proteina a ser consultada já verifica a pontuação dos epítopos
                    if (p != null) {
                        ArrayList<Epitopo> ep = buscaEpitopo(p);
                        if (!ep.isEmpty()) {
                            for (int k = 0; k < ep.size(); k++) {
                                somaSYFPEITHI = somaSYFPEITHI + 1.0 / ep.get(k).getRank();
                            }
                        }
                    }
                }
            }
            setValuePBar(i + 1);
        }

        this.notaDosSites(somaBimas, somaIEDB_consensus, somaNETMHC, somaSYFPEITHI);
    }

    //obtem a nota de cada site
    private void notaDosSites(double somaBimas, double somaIEDB_consensus, double somaNETMHC, double somaSYFPEITHI) {
        DecimalFormat df = new DecimalFormat("0.##");
        double notaBimas = 0.0, notaNETMHC = 0.0, notaIEDB_consensus = 0.0, notaSYFPEITHI = 0.0;

        Tabelas.getTabelaNotaDoSite().delete(nomeCalibragem);//exclui os calibradores com o mesmo nome
        for (int j = 0; j < motores.size(); j++) {
            if (motores.get(j).equals("Bimas")) {
                notaBimas = 10.0 * somaBimas / l_calibradores.size();

                String idSite = Tabelas.getTabelaSites().getIdSite("Bimas");
                if (idSite.equals("null")) {
                    Tabelas.getTabelaSites().insert("Bimas", "");
                    idSite = Tabelas.getTabelaSites().getIdSite("Bimas");
                }
                if (somaBimas != 0.0) {
                    Tabelas.getTabelaNotaDoSite().insert(nomeCalibragem, idSite, df.format(notaBimas).replace(",", "."), this.alelo, this.tamanho);
                }
            }

            if (motores.get(j).equals("NETMHC")) {
                notaNETMHC = 10.0 * somaNETMHC / l_calibradores.size();

                String idSite = Tabelas.getTabelaSites().getIdSite("NETMHC");
                if (idSite.equals("null")) {
                    Tabelas.getTabelaSites().insert("NETMHC", "");
                    idSite = Tabelas.getTabelaSites().getIdSite("NETMHC");
                }
                if (somaNETMHC != 0.0) {
                    Tabelas.getTabelaNotaDoSite().insert(nomeCalibragem, idSite, df.format(notaNETMHC).replace(",", "."), this.alelo, this.tamanho);
                }
            }

            if (motores.get(j).equals("IEDB_consensus")) {
                notaIEDB_consensus = 10.0 * somaIEDB_consensus / l_calibradores.size();

                String idSite = Tabelas.getTabelaSites().getIdSite("IEDB_consensus");
                if (idSite.equals("null")) {
                    Tabelas.getTabelaSites().insert("IEDB_consensus", "");
                    idSite = Tabelas.getTabelaSites().getIdSite("IEDB_consensus");
                }

                if (somaIEDB_consensus != 0.0) {
                    Tabelas.getTabelaNotaDoSite().insert(nomeCalibragem, idSite, df.format(notaIEDB_consensus).replace(",", "."), this.alelo, this.tamanho);
                }
            }
//
            if (motores.get(j).equals("SYFPEITHI")) {
                notaSYFPEITHI = 10.0 * somaSYFPEITHI / l_calibradores.size();

                String idSite = Tabelas.getTabelaSites().getIdSite("SYFPEITHI");
                if (idSite.equals("null")) {
                    Tabelas.getTabelaSites().insert("SYFPEITHI", "");
                    idSite = Tabelas.getTabelaSites().getIdSite("SYFPEITHI");
                }
                if (somaSYFPEITHI != 0.0) {
                    Tabelas.getTabelaNotaDoSite().insert(nomeCalibragem, idSite, df.format(notaSYFPEITHI).replace(",", "."), this.alelo, this.tamanho);
                }
            }
        }

        //imprime as notas        
        for (int k = 0; k < motores.size(); k++) {
            if (motores.get(k).equals("Bimas")) {
                printNota("Bimas = " + df.format(notaBimas));
            }
            if (motores.get(k).equals("NETMHC")) {
                printNota("NETMHC = " + df.format(notaNETMHC));
            }
            if (motores.get(k).equals("IEDB_consensus")) {
                printNota("IEDB_consensus = " + df.format(notaIEDB_consensus));
            }
            if (motores.get(k).equals("SYFPEITHI")) {
                printNota("SYFPEITHI = " + df.format(notaSYFPEITHI));
            }
        }

    }

    private ArrayList<Epitopo> buscaEpitopo(Proteina p) {
        ArrayList<Epitopo> ep = new ArrayList<Epitopo>();

        for (int i = 0; i < l_calibradores.size(); i++) {

            String epitopo = l_calibradores.get(i)[0];
            String proteina = l_calibradores.get(i)[1];

            if (p.getCodProteina().equals(proteina)) {
                ArrayList<Epitopo> lEp = p.getListaDeEpitopos();
                for (int j = 0; j < lEp.size(); j++) {
                    if (lEp.get(j).getNomeEpitopo().equals(epitopo)) {
                        ep.add(lEp.get(j));
                    }
                }
            }

        }

        return ep;
    }

    private Proteina executaBimas(Fasta p1) {
        Proteina prot = null;
        try {
            prot = Bimas.processCalibragem(p1.getSequencia(), alelo, tamanho, p1.getCodProteina(), "Bimas");
            if (prot != null) {
                prot.setCabecalho(p1.getInformacao());
            }

        } catch (IOException ex) {
            //jTextAreaAvisos.append("\nError in consultation Bimas.);
        }
        return prot;
    }

    private Proteina executaNETMHC(Fasta p1) {
        Proteina prot = null;
        try {

            prot = NETMHC.processCalibragem(p1.getSequencia(), alelo, tamanho, p1.getCodProteina(), "NETMHC");
            if (prot != null) {
                prot.setCabecalho(p1.getInformacao());
            }

        } catch (IOException ex) {
            //jTextAreaAvisos.append("\nError in consultation NETMHC!\n" + ex.getMessage() + "\n");
        }
        return prot;
    }

    private Proteina executaIEDB_consensus(Fasta p1) {
        Proteina prot = null;

        try {
            prot = IEDB_consensus.processCalibragem(p1.getSequencia(), alelo, tamanho, p1.getCodProteina(), "IEDB_consensus");
            if (prot != null) {
                prot.setCabecalho(p1.getInformacao());
            }
        } catch (IOException ex) {
            //jTextAreaAvisos.append("\nError in consultation IEDB_consensus!\n" + ex.getMessage() + "\n");
        }

        return prot;
    }

    private Proteina executaSYFPEITHI(Fasta p3) {
        Proteina prot = null;

        String r = p3.getSequencia().replace("\n", "");
        r = r.replace(" ", "");
        int N = r.length();
        int D = 2047;

        int n_pedacos = (int) Math.ceil(N / 2048.0);
        // System.out.println(N + " , " + n_pedacos);

        try {
            int inicio = 0;
            int fim = 0;
            if (N <= 2048) {
                fim = N - 1;
            } else {
                fim = D;
            }
            for (int k = 0; k < n_pedacos; k++) {

                //System.out.println(inicio + " - " + fim);
                String R = r.substring(inicio, fim);

                prot = SYFPEITHI.processCalibragem(R, alelo, tamanho, p3.getCodProteina(), "SYFPEITHI");

                if (prot != null) {
                    prot.setCabecalho(p3.getInformacao());
                }
                inicio = fim;

                if (N >= (D * (k + 2))) {
                    fim = D * (k + 2);
                } else {
                    fim = N - 1;
                }

            }
        } catch (IOException ex) {

        }
        return prot;
    }

}
